use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub enum SimdError {
    ComputationError(String),
    InvalidInputLength(String),
    ValidationError(String),
}

impl fmt::Display for SimdError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            SimdError::ComputationError(msg) => write!(f, "Computation error: {}", msg),
            SimdError::InvalidInputLength(msg) => write!(f, "Invalid input length: {}", msg),
            SimdError::ValidationError(msg) => write!(f, "Validation error: {}", msg),
        }
    }
}

impl Error for SimdError {}

pub type SimdResult<T> = Result<T, SimdError>;

#[derive(Debug, Clone)]
pub struct MacdResult {
    pub fast_ema: Vec<f64>,
    pub slow_ema: Vec<f64>,
    pub macd: Vec<f64>,
    pub signal: Vec<f64>,
    pub histogram: Vec<f64>,
}

impl MacdResult {
    pub fn with_capacity(size: usize) -> Self {
        Self {
            fast_ema: Vec::with_capacity(size),
            slow_ema: Vec::with_capacity(size),
            macd: Vec::with_capacity(size),
            signal: Vec::with_capacity(size),
            histogram: Vec::with_capacity(size),
        }
    }

    pub fn validate(&self) -> SimdResult<()> {
        let len = self.fast_ema.len();
        if self.slow_ema.len() != len || 
           self.macd.len() != len || 
           self.signal.len() != len || 
           self.histogram.len() != len {
            return Err(SimdError::ValidationError(
                "All MACD result vectors must have the same length".to_string()
            ));
        }
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub struct BollingerResult {
    pub middle: Vec<f64>,
    pub upper: Vec<f64>,
    pub lower: Vec<f64>,
    pub bandwidth: Vec<f64>,
    pub std_dev: Vec<f64>,
}

impl BollingerResult {
    pub fn with_capacity(size: usize) -> Self {
        Self {
            middle: Vec::with_capacity(size),
            upper: Vec::with_capacity(size),
            lower: Vec::with_capacity(size),
            bandwidth: Vec::with_capacity(size),
            std_dev: Vec::with_capacity(size),
        }
    }

    pub fn validate(&self) -> SimdResult<()> {
        let len = self.middle.len();
        if self.upper.len() != len || 
           self.lower.len() != len || 
           self.bandwidth.len() != len || 
           self.std_dev.len() != len {
            return Err(SimdError::ValidationError(
                "All Bollinger result vectors must have the same length".to_string()
            ));
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Copy)]
pub struct MacdParams {
    pub fast_period: usize,
    pub slow_period: usize,
    pub signal_period: usize,
}

impl Default for MacdParams {
    fn default() -> Self {
        Self {
            fast_period: 12,
            slow_period: 26,
            signal_period: 9,
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct BollingerParams {
    pub period: usize,
    pub num_std: f64,
}

impl Default for BollingerParams {
    fn default() -> Self {
        Self {
            period: 20,
            num_std: 2.0,
        }
    }
}